package com.modernyuanshiren;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

public abstract class AbstractAction<T extends AbstractStatus<T, U>, U extends ISingleAction<T, U>>
		implements IAction<T, U> {
	private List<IElement> elements;

	private U action;

	public AbstractAction(List<IElement> elements, U action) {
		super();
		this.elements = elements;
		this.action = action;
	}

	@SuppressWarnings("unchecked")
	public T apply(T origin) {
		List<IElement> list = getElements();
		List<IElement> all = origin.getAllElements().stream().map(Element::new)
				.collect(Collectors.toList());
		Map<IElement, Long> counted = list.stream().collect(
				Collectors.groupingBy(Function.identity(),
						Collectors.counting()));
		List<IElement> elements = new ArrayList<>();
		for (IElement t : list.stream().distinct().collect(Collectors.toList())) {
			int count = 0;
			for (IElement element : all) {
				if (element.equals(t) && count < counted.get(t)) {
					elements.add(element);
					count++;
					if (count == counted.get(t)) {
						break;
					}
				}
			}
		}
		T result = null;
		try {
			getAction().apply(elements, origin);
			result = (T) origin.getClass().newInstance();
			result.setElements(all);
		} catch (InstantiationException | IllegalAccessException e) {
			e.printStackTrace();
		}
		return result;
	};

	@Override
	public List<IElement> getElements() {
		return elements;
	}

	@Override
	public U getAction() {
		return action;
	}

}
